/******************************************************************************
 * $Id: sys_unix.c,v 1.20 2004/09/22 01:14:23 jimb Exp $
 * @file
 * @author  Jim Brooks http://www.jimbrooks.org
 * @brief   Generic UNIX functions to support hypersrc.
 ******************************************************************************/

#include "common.h"
#include "sys.h"

#include "statusbar.h"
#include "text.h"
#include "widgets.h"

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>

#include <setjmp.h>
extern sigjmp_buf main_sigjump;

/*****************************************************************************
 * Segfault handler.
 *****************************************************************************/
#ifndef HYPERSRC_DEBUG
static void
sig_segv( int signo )
{
   static int cnt	= 0;
   static int limit	= 3;

   ErrorMsgCr();
   ErrorMsg( "Dooohhh!!! " );
   ErrorMsg( "hypersrc caught a SIGSEGV." );

   if ( cnt++ >= limit )
   {
     /*
      * This handler was invoked too many times.
      */
      ErrorMsg( "GAME OVER" );
      gtk_exit( 1 );
   }

  /*
   * Print info to aid debugging.
   */
   if ( ActiveModule()  &&  ActiveModule()->pModuleName )
   {
      ErrorMsg( "module being browsed was: %s ", ActiveModule()->pModuleName );
      if ( scrolling )
      {
         ErrorMsg( "Crash occurred while scrolling." );
         ErrorMsg( "Line being scrolled to was %d ", scrollLine );
      }
   }

   ErrorMsg( "I'm gonna try to stumble onward..." );
   SysInstallSignalHandlers();
   ResetFunctions();
   SetSensitivityWhileBusy_cnt = 0;
   SetSensitivityWhileBusy( TRUE );
   siglongjmp( main_sigjump, 0 );
}
#endif /* !HYPERSRC_DEBUG */

/*****************************************************************************
 * Called by hypersrc to install system-specific signal handlers.
 *****************************************************************************/
void
SysInstallSignalHandlers( void )
{
  /*
   * GNOME has installed its own SIGSEGV handler.
   * For debugging, reinstall the default handler to dump core.
   */
#ifdef HYPERSRC_DEBUG
   signal( SIGSEGV, SIG_DFL );
#else
   signal( SIGSEGV, sig_segv );

#endif
}

/*****************************************************************************
 * Execute a program (without waiting).
 *****************************************************************************/
void
SysExec( char*  pFilename,
         char** ppExecArgs )
{
   pid_t	pid;

   pid = fork();

   if ( pid > 0 )
   {
     /*
      * This is the parent process.
      */
      return;      
   }
   else if ( pid == 0 )
   {
     /*
      * This is the child process.
      */
      execvp( pFilename, ppExecArgs );

     /*
      * exec*() isn't supposed to return.
      */
      Warning( "execvp('%s') failed.", pFilename );
      perror( "" );
      PrintStatusbarThirds( "Failed to invoke '", pFilename, "'." );
      _exit(-1); /* instead of exit() -- see GTK+ FAQ for why */
   }
   else /* pid < 0 */
   {
      Warning( "fork() failed." );
      perror("");
      return;
   }
}
